package com.zhou.core.redis;

import com.zhou.ConsoleSystem;
import com.zhou.ToolsApp;
import com.zhou.util.PropertyFileReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Protocol;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * Jedis session pool
 */
public class RedisSessionService implements ConsoleSystem {
    private static final Logger logger = LoggerFactory.getLogger(RedisSessionService.class);
    private static final RedisSessionService instance = new RedisSessionService();
    private JedisPool defaultJedisPool = null;
    Map<String,JedisPool> jedisPools = null;
    private RedisSessionService() {
    }

    public Jedis getResource() {
        return defaultJedisPool.getResource();
    }

    public Jedis getResource(String redisFileName)
    {
        if (jedisPools == null)
        {
            jedisPools = new HashMap<String, JedisPool>();
        }
        try {
            JedisPool jedisPool =jedisPools.get(redisFileName);
            if (jedisPool == null) {
                PropertyFileReader propertyFileReader = new PropertyFileReader();
                propertyFileReader.load(redisFileName);
                jedisPool = initPool(propertyFileReader);
                jedisPools.put(redisFileName, jedisPool);
            }
            logger.debug(redisFileName + " : numIdle=" + jedisPool.getNumIdle()+",numActive="+jedisPool.getNumActive()+",numWaiters="+jedisPool.getNumWaiters()+",getMaxBorrowWaitTimeMillis="+jedisPool.getMaxBorrowWaitTimeMillis()+",getMeanBorrowWaitTimeMillis="+jedisPool.getMeanBorrowWaitTimeMillis());
            return jedisPool.getResource();
        }catch(Exception e)
        {
            logger.error("error : load redis resouces ["+redisFileName+"]",e);
        }
        return null;
    }


    public Jedis getResource(String redisFileName,PropertyFileReader propertyFileReader)
    {
        if (jedisPools == null)
        {
            jedisPools = new HashMap<String, JedisPool>();
        }
        try {
            JedisPool jedisPool =jedisPools.get(redisFileName);
            if (jedisPool == null) {
                jedisPool = initPool(propertyFileReader);
                jedisPools.put(redisFileName, jedisPool);
            }
            logger.debug(redisFileName + " : numIdle=" + jedisPool.getNumIdle()+",numActive="+jedisPool.getNumActive()+",numWaiters="+jedisPool.getNumWaiters()+",getMaxBorrowWaitTimeMillis="+jedisPool.getMaxBorrowWaitTimeMillis()+",getMeanBorrowWaitTimeMillis="+jedisPool.getMeanBorrowWaitTimeMillis());
            return jedisPool.getResource();
        }catch(Exception e)
        {
            logger.error("error : load redis resouces ["+redisFileName+"]",e);
        }
        return null;
    }


    public void close(Jedis resource) {
//        defaultJedisPool.returnResource(resource);
        resource.close();
    }

    public void closeBroken(Jedis resource) {
        resource.close();
    }

    public void initDefaultPool() throws IOException {
        PropertyFileReader propertyFileReader = new PropertyFileReader();
        propertyFileReader.load(RedisConst.DEFAULT_FILE_NAME);
       this.defaultJedisPool = initPool(propertyFileReader);
    }

    private JedisPool initPool(PropertyFileReader propertyFileReader) {
        JedisPoolConfig poolConfig = new JedisPoolConfig();

        poolConfig.setMaxTotal(propertyFileReader.getInt(RedisConst.CONFIG_KEY_MAX_ACTIVE,30));
        poolConfig.setMaxIdle(propertyFileReader.getInt(RedisConst.CONFIG_KEY_MAX_IDLE,20));
        
        poolConfig.setMaxWaitMillis(propertyFileReader.getLong(RedisConst.CONFIG_KEY_MAX_WAIT,5000));
        poolConfig.setTestOnBorrow(propertyFileReader.getBooolean(RedisConst.CONFIG_KEY_TEST_ON_BORROW,true));
        poolConfig.setTestOnReturn(propertyFileReader.getBooolean(RedisConst.CONFIG_KEY_TEST_ON_RETURN,true));
        int useIdle = propertyFileReader.getInt(RedisConst.CONFIG_KEY_USE_INDEX,Protocol.DEFAULT_DATABASE);
        String redisIp = propertyFileReader.getString(RedisConst.CONFIG_KEY_IP,"localhost");
        int redisPort = propertyFileReader.getInt(RedisConst.CONFIG_KEY_PORT,6379);
        JedisPool jedisPool = new JedisPool(poolConfig, redisIp, redisPort,Protocol.DEFAULT_TIMEOUT,null,useIdle);
        
        logger.info("init local redis pool redisIp:" + redisIp + " redisPort:" + redisPort+" useIdle:"+useIdle+"  sucess!");
        return jedisPool;
    }

    @Override
    public ToolsApp.SystemType getConsoleSubSystemType() {
        return ToolsApp.SystemType.REDIS ;
    }

    @Override
    public void startup(Object... params) throws Throwable {
        initDefaultPool();
    }

    @Override
    public void shutdown(Object... params) throws Throwable {
        if (defaultJedisPool != null)
        {
            defaultJedisPool.close();
            defaultJedisPool = null;
        }
        if (jedisPools != null)
        {
            for (JedisPool pool : jedisPools.values())
            {
                pool.close();
            }
            jedisPools = null;
        }

    }

    @Override
    public boolean isStartUp() {
        return false;
    }

    public static RedisSessionService getInstance() {
        return instance;
    }
}
